﻿using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Web.Mvc;
using SDCloudSolution.SDCloud.Web.Infrastructure.Interfaces;
using SDCloudSolution.SDCloud.Web.Models;
using SDCloudSolution.SDCloud.Web.Models.Model;
using SDCloudSolution.SDCloud.Entities.Models;
using SDCloudSolution.SDCloud.DataLayer.Model;
using SDCloudSolution.SDCloud.DataLayer.ModelData;

namespace SDCloudSolution.SDCloud.Web.Controllers
{
    [RoutePrefix("models")]
    [Authorize]
    public partial class ModelsController : Controller
    {
        private readonly IModelViewModelProvider _modelProvider;
        private readonly MongoModelMetadataDataProvider _metadataProvider;

        public ModelsController(IModelViewModelProvider modelProvider,
                                MongoModelMetadataDataProvider metadataProvider)
        {
            _modelProvider = modelProvider;
            _metadataProvider = metadataProvider;
        }

        [Route("list")]
        [HttpGet]
        public virtual async Task<ActionResult> List(PagingModel paging = null)
        {
            paging = PagingModel.Default;

            var model = await _modelProvider.GetModelsListViewModelAsync(paging);

            return View(model);
        }
        
        [HttpGet]
        public virtual async Task<ActionResult> View(int modelId)
        {
            var model = await _modelProvider.GetModelViewModelAsync(modelId);
            var metadata = await _metadataProvider.GetMetadataByModelIdAsync(modelId);
            if (null != model)
            {
                model.Metadata = metadata;
            }
            return View(model);
        }

        [Route("{modelId}/download")]
        [HttpGet]
        public virtual async Task<ActionResult> Download(int modelId)
        {
            if (modelId <= 0)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var model = await _modelProvider.GetModelViewModelAsync(modelId);
            var modelFileStream = await _modelProvider.GetModelFileStreamAsync(modelId);

            Response.AddHeader("Content-Disposition", $"attachment;filename={model.FileName}");
            return File(modelFileStream, GetContentTypeForModelFile(model.FileName));
        }

        private string GetContentTypeForModelFile(string fileName)
        {
            var extension = Path.GetExtension(fileName);

            if (extension == ".xmile")
            {
                return "application/xml";
            }

            if (extension == ".mdl")
            {
                return "text/plain";
            }

            return "text/plain";
        }

        [Route("{modelId}/edit")]
        [HttpGet]
        public virtual async Task<ActionResult> Edit(int modelId)
        {
            var model = await _modelProvider.GetModelEditViewModelAsync(modelId);
            return View(model);
        }


        [Route("create")]
        public virtual async Task<ActionResult> Create()
        {
            var model = await _modelProvider.GetModelEditViewModelAsync();

            return View(MVC.Models.Views.Edit, model);
        }

        [Route("save")]
        [HttpPost]
        public virtual async Task<ActionResult> Save(ModelEditViewModel editViewModel)
        {
           // _modelProvider.ValidateModelUploadedFile(editViewModel, ModelState);

           // if (ModelState.IsValid)
            {
                var entity = await _modelProvider.SaveAsync(editViewModel);

                if (editViewModel.ModelFile.FileName.EndsWith(".xmile"))
                {
                    ModelMetadataEntity modelMetadata =
                    ModelMetadataDataProvider.GetXmileModelMetadata(
                        editViewModel.ModelFile.InputStream);
                    modelMetadata.ModelId = entity.Id;

                    await _metadataProvider.InsertAsync(modelMetadata);
                }

                return RedirectToAction(MVC.Models.View(entity.Id));
            }

            return View(MVC.Models.Views.Edit, editViewModel);
        }

        [Route("{modelId}/delete")]
        [HttpPost]
        public virtual async Task<ActionResult> Delete(int modelId)
        {
            await _modelProvider.DeleteAsync(modelId);
            await _metadataProvider.DeleteAsync(modelId);

            return Redirect(Url.Action(MVC.Models.List()));
        }
    }
}